package auctionhaus

import grails.converters.JSON
import grails.gorm.DetachedCriteria
import org.codehaus.groovy.grails.web.mapping.LinkGenerator

class CompletedListingService {

	def emailService
	def jmsService
	def crudService
	LinkGenerator grailsLinkGenerator

	//C-1: When a listing completes post a message to a JMS Queue representing sending the completed listing information 
	//including listing details, seller and winner information as XML or JSON (you choose). Test this with an integration test.
	def synchronized postListingCompletedMessages() {
		List completedListings = findCompletedListingsforMessage()
		println("There are "+completedListings.size() +" new completed listings to publish @ " + new Date()+".");
		JSON.use("deep")
		if(completedListings.size() > 0) {
			for (listing in completedListings) {

				if(listing.winner==null){
					findWinner(listing)
				}

				def converter = listing as JSON
				converter.prettyPrint = true
				updateListingForMessage(listing)
				def message = converter.toString()
				def th = Thread.start {
					jmsService.send(queue: 'queue', message)
				}
				
				
			}
		}
	}

	def findWinner(Listing listing){
		if(listing.winner == null){
			if(listing.bids.size()>0){
				listing.winner = listing.bids[listing.bids.size()-1].bidder
				listing.save(flush:true)
			}
		}
	}

	//C-2: When a listing completes, send a confirmation email to the winner and the lister with a link to the listing information 
	//and the final price. (integration test for extra credit)
	def synchronized sendListingsCompletedEmails() {
		List completedListings = findCompletedListingsforEmail()
		println("There are "+completedListings.size() +" new completed listings to email @ " + new Date()+".")
		if(completedListings.size() > 0) {
			for (listing in completedListings) {
				if(listing.winner==null){
					findWinner(listing)
				}

				updateListingForEmail(listing)
				List messages = getMessages(listing)
				emailService.sendEmails(messages)

			}
		}
	}

	def List findCompletedListingsforMessage() {
		def criteria
		criteria = new DetachedCriteria(Listing).build {
			lt 'endDateTime',(new Date())
			eq 'sentMessage', false
		}
		List completedListings = criteria.list()

		return completedListings;
	}

	def List findCompletedListingsforEmail() {
		def criteria
		criteria = new DetachedCriteria(Listing).build {
			lt 'endDateTime',(new Date())
			eq 'sentEmail', false
		}
		List completedListings = criteria.list()

		return completedListings;
	}

	def List getMessages(Listing listing)
	{
		List messages = new ArrayList()
		def sellerMessage = generateMessage(true, listing)
		messages.add(sellerMessage)
		if(listing.winner!=null){
			def winnerMessage = generateMessage(false, listing)
			messages.add(winnerMessage)
		}
		return messages
	}
	def EmailMessage generateMessage(boolean isSeller, Listing listing)
	{
		EmailMessage message = new EmailMessage()

		def sender = getSender()
		def finalPrice = getFinalBidPrice(listing)
		def recipient
		def subject
		def body

		if(isSeller) //boolean
		{
			Customer seller =  listing.seller
			recipient = seller.username
			subject = getEmailSubject(true,listing,finalPrice)
			body = getEmailBody(true,listing,finalPrice)
		}
		else
		{

			Customer winner =  listing.winner
			recipient = winner.username
			subject = getEmailSubject(false,listing,finalPrice)
			body = getEmailBody(false,listing,finalPrice)

		}
		message.setRecipient(recipient)
		message.setSender(sender)
		message.setSubject(subject)
		message.setBody(body)

		return message
	}

	def Float getFinalBidPrice(Listing listing)
	{
		def finalPrice = 0
		int size = listing.bids.size()
		if(size>0)
		{
			Bid lastBid = (Bid) listing.bids[size-1]
			finalPrice = lastBid.amount
		}
		return finalPrice
	}
	def synchronized Listing updateListingForMessage(Listing listing) {

		Listing latestListing = Listing.findById(listing.id)
		latestListing.sentMessage = true
		latestListing.isFinished = true
		crudService.updateListing(latestListing)
	
		return latestListing
	}
	def synchronized Listing updateListingForEmail(Listing listing) {

		Listing latestListing = Listing.findById(listing.id)
		latestListing.sentEmail = true
		latestListing.isFinished = true
		crudService.updateListing(latestListing)
		
		return latestListing
	}

	def getSender()
	{
		return "auctionhaus2012@gmail.com"
	}
	def getEmailSubject(boolean isSeller, Listing listing, float finalPrice)
	{
		if (isSeller)
		{
			return "Your listing ${listing.name} (#${listing.id}) has completed."
		}
		return "Congratulations! You are the winner of this Listing ${listing.name} (#${listing.id})!"
	}

	def getEmailBody(boolean isSeller, Listing listing,float finalPrice)
	{

		String link = grailsLinkGenerator.link(controller: 'listing', action: 'showPermanentDetails', id: listing.id, absolute: true);

		if(isSeller)
		{
			if(listing.bids.size()==0){
				return "Your listing ${listing.name} (#${listing.id}) has completed. Here are the details for the listing: ${link}. There were no bids, please post another listing."
				
			}
			
			return "Congratulations, Your listing ${listing.name} (#${listing.id}) has completed. Here are the details for the listing: ${link}. The winning bid was ${Bid.amountFormatter(finalPrice)}."
		}
		return "Congratulations, You are the winner for listing ${listing.name} (#${listing.id}).  Here are the detail for the listings: ${link}. The winning bid was ${Bid.amountFormatter(finalPrice)}."
	}
}
